package cn.coisini.kafka.listtener;

import cn.coisini.model.common.constants.message.AdminMessageConstants;
import cn.coisini.model.common.enums.ResultEnum;
import cn.coisini.model.common.exception.CustomAuthenticationException;
import cn.coisini.model.common.mail.MailService;
import cn.coisini.model.pojo.AsyncLoginLog;
import cn.coisini.model.pojo.User;
import cn.coisini.security.auth.AuthUser;
import cn.coisini.service.UserService;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;

import static cn.coisini.model.common.constants.SecurityConstants.CAPTCHA_PREFIX;
import static cn.coisini.utils.JsonUtil.toMap;

/**
 * @author xiangshaw
 * Description: 监听 更新登录时间消息
 */
@Log4j2
@Component
@RequiredArgsConstructor
public class AsyncLoginTaskConsumer {

    private final UserService userService;
    private final MailService mailService;
    private final StringRedisTemplate stringRedisTemplate;

    // 监听更新登录时间消息
    @KafkaListener(topics = AdminMessageConstants.ADMIN_UPDATE_LOGIN_TIME, containerFactory = "kafkaListenerContainerFactory")
    public void handleLoginTimeUpdate(String message) {
        log.info("获取更新登录时间消息: {}", message);
        try {
            // 1.解析消息
            Map<String, Object> map = toMap(message);
            // 2.获取用户信息
            User user = parseUser(map);
            AuthUser authUser = parseAuthUser(map);
            // 3.校验并更新用户登录时间
            updateLoginTime(user);
            // 4.清除验证码缓存
            clearCaptchaCache(authUser);
            log.info("更新登录时间成功: 用户ID {}，验证码清除 {}", user.getId(), authUser.getUuid());
        } catch (CustomAuthenticationException e) {
            log.error("更新登录时间失败: {}", e.getMessage(), e);
            throw new CustomAuthenticationException(e.getResultEnum(), e.getMessage());
        } catch (Exception e) {
            log.error("处理消息时发生错误: {}", e.getMessage(), e);
            throw new CustomAuthenticationException(ResultEnum.DATA_NOT_UPDATE, "处理消息时发生错误");
        }
    }

    private User parseUser(Map<String, Object> map) {
        User user = JSONUtil.toBean(JSONUtil.toJsonStr(map.get("user")), User.class);
        if (user == null || user.getId() == null || user.getId().trim().isEmpty()) {
            throw new CustomAuthenticationException(ResultEnum.DATA_NOT_UPDATE, "用户ID为空");
        }
        return user;
    }

    private AuthUser parseAuthUser(Map<String, Object> map) {
        return JSONUtil.toBean(JSONUtil.toJsonStr(map.get("authUser")), AuthUser.class);
    }

    private void updateLoginTime(User user) {
        user.setLoginTime(LocalDateTime.now());
        LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(User::getId, user.getId()).set(User::getLoginTime, LocalDateTime.now());

        boolean updateCount = userService.update(user, wrapper);
        if (!updateCount) {
            throw new CustomAuthenticationException(ResultEnum.DATA_NOT_UPDATE, "更新登录时间失败: 用户ID不存在或其他错误");
        }
    }

    private void clearCaptchaCache(AuthUser authUser) {
        stringRedisTemplate.delete(CAPTCHA_PREFIX + authUser.getUuid());
    }

    // 监听发送登录邮件消息
    @KafkaListener(topics = AdminMessageConstants.ADMIN_SEND_LOGIN_MAIL, containerFactory = "kafkaListenerContainerFactory")
    public void handleSendLoginSuccessMail(String message) {
        log.info("获取发送登录邮件消息: {}", message);
        try {
            // 1. 解析消息
            Map<String, Object> map = toMap(message);
            // 2.获取用户信息
            User user = parseUser(map);
            AsyncLoginLog asyncLoginLog = parseAsyncLoginLog(map);
            // 3.发送邮件
            sendLoginSuccessMail(user, asyncLoginLog);
        } catch (Exception e) {
            log.error("处理消息时发生错误: {}", e.getMessage(), e);
        }
    }

    private AsyncLoginLog parseAsyncLoginLog(Map<String, Object> map) {
        return JSONUtil.toBean(JSONUtil.toJsonStr(map.get("asyncLoginLog")), AsyncLoginLog.class);
    }

    /**
     * 发送登录成功邮件
     *
     * @param user          用户信息
     * @param asyncLoginLog 登录日志
     */
    private void sendLoginSuccessMail(User user, AsyncLoginLog asyncLoginLog) {
        String htmlContent = "<html>" +
                "<body style='font-family: Arial, sans-serif; color: #333; line-height: 1.6;'>" +
                "<div style='max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e0e0e0;'>" +
                "   <h2 style='color: #2E86C1;'>coisini技术探索 - 新的登录活动通知</h2>" +
                "   <p>您好，" + user.getNickName() + "，</p>" +
                "   <p>我们注意到您的账户在以下位置进行了登录：</p>" +
                "   <ul style='list-style-type: none; padding: 0;'>" +
                "       <li><strong>登录 IP:</strong> " + asyncLoginLog.getLoginIp() + "</li>" +
                "       <li><strong>登录地点:</strong> " + asyncLoginLog.getLoginIpSource() + ", " + asyncLoginLog.getLoginIpCity() + "</li>" +
                "       <li><strong>登录时间:</strong> " + ZonedDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "</li>" +
                "   </ul>" +
                "   <p style='margin-top: 20px;'>如果您确认是本人操作，可以忽略此通知。若您有疑问，请及时联系我们。</p>" +
                "   <p>祝您使用愉快！<br/>" +
                "       <a href='https://coisini.cn' style='color: #D91AD9; text-decoration: none;'>coisini技术探索</a>" +
                "   </p>" +
                "</div>" +
                "</body>" +
                "</html>";

        mailService.sendMail(
                user.getEmail(),
                "coisini技术探索 有新的登录活动",
                htmlContent
        );
    }
}
